package com.youku.component.procedure;

import java.sql.Connection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.junit.Assert;

import com.youku.component.CaseStep;
import com.youku.component.TestCase;
import com.youku.component.result.ExecuteResult;
import com.youku.expression.Expression;
import com.youku.expression.Position;
import com.youku.util.StringHelper;

/**
 * 数据库数据库执行过程
 * 
 * @author loda
 *
 */
public class SQLProcedure extends AbstractProcedure {

	private static final Map<String, SQLExecutor> EXECUTOR_MAP;

	static {
		EXECUTOR_MAP = new HashMap<>();

		EXECUTOR_MAP.put("select", new QuerySQLExecutor());
		EXECUTOR_MAP.put("update", new UpdateSQLExecutor());
		EXECUTOR_MAP.put("insert", new UpdateSQLExecutor());
		EXECUTOR_MAP.put("delete", new UpdateSQLExecutor());
	}

	private Connection connection;

	private List<SQLExecutor> executors = new LinkedList<>();

	private Expression sql;

	public SQLProcedure(String id, TestCase testCase, String times) {
		super(id, testCase, times);
	}

	public SQLProcedure() {
	}

	public void setSql(String sqlString) {
		this.sql = createExpression(sqlString);
	}

	public Connection getConnection() {
		return connection;
	}

	public void setConnection(Connection connection) {
		this.connection = connection;
	}

	/**
	 * 启动后会执行的方法
	 */
	@Override
	public void invoke() {
		String[] sqlArr = StringUtils.split(sql.get(), ';');

		if (sqlArr.length == 0)
			return;

		// 为每个sql语句分配执行器(query or update)
		for (String s : sqlArr) {
			SQLExecutor executor = EXECUTOR_MAP.get(StringHelper.firstWord(s));

			Assert.assertNotNull("sql类型错误", executor);

			executor.setSql(s);

			executors.add(executor);
		}

		// 执行多条sql语句，将最后一条语句的执行结果记录下来
		ExecuteResult result = null;
		for (SQLExecutor executor : executors) {
			result = executor.execute(connection);
		}

		results.add(result);
	}

	@Override
	public void updatePosition(Position position) {
		super.updatePosition(position);
		sql.setPosition(position);
	}

	@Override
	public CaseStep cloneStep() {
		SQLProcedure procedure = new SQLProcedure();
		procedure.connection = connection;
		procedure.executors = executors;
		procedure.id = id;
		procedure.results = results;
		procedure.sql = new Expression(sql.getPosition(), sql.getExpressionString());
		procedure.testCase = testCase;
		procedure.times = new Expression(times.getPosition(), times.getExpressionString());
		return procedure;
	}
}
